#include <iostream>
#include <string>
#include <bitset>
#include <vector>
#include "data.hpp"

using namespace std;



typedef struct data64
{
	bitset<64> bits;
}datas_64;


typedef struct data56
{
	bitset<56> bits;
}datas_56;

typedef struct data48
{
	bitset<48> bits;
}datas_48;

typedef struct data32
{
	bitset<32> bits;
}datas_32;

typedef struct data28
{
	bitset<28> bits;
}datas_28;

typedef struct data6
{
	bitset<6> bits;
}datas_6;

typedef struct data4
{
	bitset<4> bits;
}datas_4;

typedef struct data2
{
	bitset<2> bits;
}datas_2;



datas_48 K_i[16];
datas_64 secret_key;



void init_secret_key(); //初始化密钥
void init_K_i(datas_64 secret_key);//初始化子密钥ki
string RKCS_fill(string str);  //RKCS#5补齐8个字节
vector<datas_64> string_to_binary(string str);  //将字符串转化为二进制数
string binary_to_string(vector<datas_64> v);  //将二进制数转化为字符串
vector<datas_64> encryption(vector<datas_64> v); //所有数据的加密算法，第二个参数为密钥
vector<datas_64> Decrypt(vector<datas_64> v); //所有数据的解密算法，第二个参数为密钥
datas_64 byte_encryption(datas_64 v); //64位的加密算法 
datas_64 byte_Decrypt(datas_64 v);  //64位的解密算法
datas_64 IP(datas_64 v); //IP置换
datas_64 IP_inverse(datas_64 v); //IP的逆置换
datas_64 W(datas_64 v);   //W操作
datas_64 T_iteration(datas_64 v, datas_48* K);  //16次T迭代,注意，算法最后的左右交换输出就是W操作，在这里不写，不要重复！！
datas_64 T_iteration_inverse(datas_64 v, datas_48* K);   //16次T的逆迭代，算法最后的左右交换输出就是W操作，在这里不写，不要重复！！
datas_32 Feistel(datas_32 R, datas_48 K); //Feistel轮函数
datas_48 E_extend(datas_32 v); //E-扩展
datas_32 S_box_change(datas_48 v); //s盒6-4转化，48位转位32位
datas_4 find_in_Sbox(int index, datas_6 v); //6-4转化，输入一个6位，输出一个4位，index位第index个S-BOX
datas_32 P(datas_32 v); //Feistel轮函数中的P置换





int main(){
	init_secret_key();
	init_K_i(secret_key);




	string Plaintext = "";
	char c;
	cout << "输入明文： ";
	while((c = cin.get()) != '\n'){
		Plaintext += c;
	}

	Plaintext = RKCS_fill(Plaintext);
	vector<datas_64> v = string_to_binary(Plaintext);
	vector<datas_64> data1 = encryption(v);
	cout << "密文:  " << binary_to_string(data1) << endl;
	vector<datas_64> data2 = Decrypt(data1);
	cout << "解密后明文:  " << binary_to_string(data2) << endl;
	

	return 0;
}


void init_secret_key(){
	for(int i = 0; i < 64; i = i + 2){
		secret_key.bits.set(i, 1); 
	}
}


void init_K_i(datas_64 secret_key){  //right
	datas_56 data;
	for(int i = 0; i < 56; i++){
		data.bits.set(i, secret_key.bits[PC1_Table[i]-1]);   //PC-1置换
	}
	datas_28 C;
	datas_28 D;
	for(int i = 0; i < 28; i++){
		C.bits.set(i, data.bits[i]);
	}
	for(int i = 28; i < 56; i++){
		D.bits.set(i-28, data.bits[i]);
	}
	for(int i = 1; i <= 16; i++){
		if(i == 1 || i == 2 || i == 9 || i == 16){
			C.bits = C.bits << 1;
			D.bits = D.bits << 1;
		}
		else{
			C.bits = C.bits << 2;
			D.bits = D.bits << 2;
		}
		for(int t = 0; t < 28; t++){
			data.bits.set(t, C.bits[t]);
			data.bits.set(t+28, D.bits[t]);
		}

		for(int t = 0; t < 48; t++){
			K_i[i-1].bits.set(t, data.bits[PC2_Table[t]-1]); //PC-2置换
		}
	}
}


string RKCS_fill(string str){  //right
	int num = 8 - str.size() % 8;
	for (int i = 0; i < num; i++){
		str += num;
	}
	//cout << "需补几个字节：" << num << endl;
	return str;
}




vector<datas_64> string_to_binary(string str){

	vector<datas_64> Plaintext_binary;
	int num = (str.size()+7) / 8;  //每8个byte（即64位）一组，总共有num组

	for(int i = 0; i < num; i++){ //有num个64位，即8个byte/char类型，一个for循环赋值一个64位bitset
		
		datas_64 data;
		for(int j = 0; j < 8; j++){  //一个for循环赋值8位，即一个字符
			int ascii = str.at(8*i + j);
			bitset<8> a(ascii);   //char(也就是int)转为bitset
			for(int t =0; t < 8; t++){   
				data.bits.set(j*8+t, a[t]);
			}
		}
		Plaintext_binary.push_back(data);
	}
	return Plaintext_binary;
}


string binary_to_string(vector<datas_64> v){
	string str = "";
	for(int i =0; i < v.size(); i++){ //每个循环翻译8byte即8个字符
		for(int j = 0; j < 8; j++){  //每个循环翻译1个字符
			bitset<8>a;
			for(int t = 0; t < 8; t++){   //1个字符8个bit
				a.set(t, v.at(i).bits[j*8 + t]);  
			}
			str += (int)(a.to_ulong()); //bitset转换为char再加入string后面
		}
	}
	return str;
}


datas_64 IP(datas_64 v){   //right
	datas_64 data;
	for(int i =0; i < 64; i++){
		data.bits.set(i, v.bits[IP_Table[i]-1]); //IP置换
	}
	return data;
}


datas_64 IP_inverse(datas_64 v){ //right
	datas_64 data;
	for(int i =0; i < 64; i++){
		data.bits.set(i, v.bits[IP_inverse_Table[i]-1]); //逆IP置换
	}
	return data;
}



//前32bits和后32bits交换
datas_64 W(datas_64 v){   //Right
	datas_64 data;
	for(int i = 0; i < 32; i++){
		data.bits.set(i, v.bits[i+32]);
		data.bits.set(i+32, v.bits[i]);
	}
	return data;
}


//E扩展  
datas_48 E_extend(datas_32 v){  //right
	datas_48 data;
	for(int i = 0; i < 48; i++){
		data.bits.set(i, v.bits[E_Table[i]-1]);
	}
	return data;
}


datas_4 find_in_Sbox(int index, datas_6 v){  //right
	datas_2 v2;
	datas_4 v4;
	v2.bits.set(0, v.bits[0]);
	v2.bits.set(1, v.bits[5]);
	for(int i = 0; i < 4; i++){
		v4.bits.set(i, v.bits[i+1]);
	}
	int row = v2.bits.to_ulong();
	int col = v4.bits.to_ulong();
	int num = S_Box[index][row][col];
	bitset<4>a(num);
	for(int i = 0; i < 4; i++){
		v4.bits.set(i, a[i]);
	}

	return v4;
}




//s盒6-4转化，48位转位32位
datas_32 S_box_change(datas_48 v){   //right
	datas_32 data;
	datas_6 data_6[8];
	datas_4 data_4[8];

	
	for(int i = 0; i < 48; i++){
		data_6[(int)(i/6)].bits.set(i%6, v.bits[i]);
	}
	for(int i = 0; i < 8; i++){
		data_4[i] = find_in_Sbox(i, data_6[i]);
	}
	
	for(int i = 0; i < 32; i++){
		data.bits.set(i, data_4[(int)(i/4)].bits[i%4]);
	}
	
	return data;
}





//Feistel轮函数
datas_32 Feistel(datas_32 R, datas_48 K){   //right
	datas_48 data = E_extend(R);
	data.bits = (data.bits ^= K.bits);
	datas_32 data_32 = S_box_change(data);
	data_32 = P(data_32);
	return data_32;
}

//Feistel轮函数中的P置换
datas_32 P(datas_32 v){  //right
	datas_32 data;
	for(int i = 0; i < 32; i++){
		data.bits.set(i, v.bits[P_Table[i]-1]);
	}
	return data;
}


//16次T迭代,注意，算法最后的左右交换输出就是W操作，不要重复！！
datas_64 T_iteration(datas_64 v, datas_48* K){  //right
	datas_64 data;
	datas_32 L, R;
	for(int i = 0; i < 32; i++){  //L0, R0
		L.bits.set(i, v.bits[i]);
		R.bits.set(i, v.bits[i+32]);
	}
	for(int i = 0; i < 16; i++){  //16次迭代
		datas_32 L_temp = L;
		datas_32 R_temp = R;
		L = R_temp;
		R.bits = (L_temp.bits ^= Feistel(R_temp, K[i]).bits);
	}
	for(int i = 0; i < 32; i++){
		data.bits.set(i, L.bits[i]);
		data.bits.set(i+32, R.bits[i]);
	}
	return W(data);
}



//16次T的逆迭代,注意，算法最后的左右交换输出就是W操作，不要重复！！
datas_64 T_iteration_inverse(datas_64 v, datas_48* K){
	datas_64 data;
	datas_32 L, R;
	for(int i = 0; i < 32; i++){  //L0, R0
		L.bits.set(i, v.bits[i]);
		R.bits.set(i, v.bits[i+32]);
	}
	for(int i = 0; i < 16; i++){  //16次迭代
		datas_32 L_temp = L;
		datas_32 R_temp = R;
		L = R_temp;
		R.bits = (L_temp.bits ^= Feistel(R_temp, K[15 - i]).bits);
	}
	for(int i = 0; i < 32; i++){
		data.bits.set(i, L.bits[i]);
		data.bits.set(i+32, R.bits[i]);
	}
	return W(data);
}


//64位的加密算法 
datas_64 byte_encryption(datas_64 v){
	datas_64 data;
	data = IP(v);
	data = T_iteration(data, K_i);
	//cout << "this is true R16L16:" << data.bits << endl;
	data = IP_inverse(data);

	return data;

} 


//64位的解密算法
datas_64 byte_Decrypt(datas_64 v){
	datas_64 data;
	data = IP(v);
	//cout << "this is after R16L16:" << data.bits << endl;
	data = T_iteration_inverse(data, K_i);
	data = IP_inverse(data);
	return data;
}



//所有数据的加密算法，第二个参数为密钥
vector<datas_64> encryption(vector<datas_64> v){
	vector<datas_64> data;
	for(int i = 0; i < v.size(); i++){
		data.push_back(byte_encryption(v.at(i)));
	}
	return data;
}




//所有数据的解密算法，第二个参数为密钥
vector<datas_64> Decrypt(vector<datas_64> v){
	vector<datas_64> data;
	for(int i = 0; i < v.size(); i++){
		data.push_back(byte_Decrypt(v.at(i)));
	}
	return data;
}
